package com.xuzmian.demo.kotlin

/**
 * 密封类：要声明一个密封类，需要在类名前面添加 sealed 修饰符。虽然密封类也可以有子类，但是所有子类都必须在与密封类自身相同的文件中声明。
 */
sealed class UiOp {
    object Show: UiOp()
    object Hide: UiOp()
    class TranslateX(val px: Float): UiOp()
    class TranslateY(val px: Float): UiOp()
}

/**
 * 密封类的用法
 */
fun sealedClassExample(op: UiOp) = when (op) {
    UiOp.Show -> println("view is show ")
    UiOp.Hide -> println("view is hide ")
    is UiOp.TranslateX -> println("view  is translationX for $op.px ")// 这个 when 语句分支不仅告诉 view 要水平移动，还告诉 view 需要移动多少距离，这是枚举等 Java 传统思想不容易实现的
    is UiOp.TranslateY -> println("view  is translationY for $op.px ")
}

/**
 * 在 Kotlin 1.1 之前， 该规则更加严格：子类必须嵌套在密封类声明的内部
 */
sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()

fun sealedClassExprExample(expr: Expr): Double = when(expr) {
    is Const -> expr.number
    is Sum -> sealedClassExprExample(expr.e1) + sealedClassExprExample(expr.e2)
    NotANumber -> Double.NaN
    // 不再需要 `else` 子句，因为我们已经覆盖了所有的情况
}